home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK1.toast / Development Kits (Disc 1) / Apple Game Sprockets / Examples / SoundSprocketTest / TS3Sound.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-16  |  16.9 KB  |  731 lines  |  [TEXT/CWIE]

  1. /*
  2.  *    File:        TS3Sound.c
  3.  *    Author:        Dan Venolia
  4.  *
  5.  *    Contents:    Handles some of the sound stuff.
  6.  *
  7.  *    Copyright © 1996 Apple Computer, Inc.
  8.  */
  9.  
  10. #include <assert.h>
  11. #include <math.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14.  
  15. #include <Components.h>
  16. #include <Controls.h>
  17. #include <Dialogs.h>
  18. #include <Sound.h>
  19. #include <Resources.h>
  20. #include <Timer.h>
  21. #include <Types.h>
  22.  
  23. #include "SoundSprocket.h"
  24.  
  25. #include "TS3Message.h"
  26. #include "TS3Resource.h"
  27. #include "TS3Sound.h"
  28. #include "TS3Utils.h"
  29. #include "TS3Window.h"
  30.  
  31. static SndChannelPtr        gSoundChannel            = NULL;
  32. static SndListHandle        gSoundResource            = NULL;
  33. static DialogPtr            gSoundDialog            = NULL;
  34. static SSpLocalizationData    gSoundPrev3DInfo;
  35.  
  36.  
  37. static Boolean CheckVersionNumber(
  38.     const NumVersion*        inVersion,
  39.     UInt8                    inMajor,
  40.     UInt8                    inMinor,
  41.     UInt8                    inBug);
  42.  
  43. static WindowMethodPtr Sound_MetaHandler(
  44.     WindowMethod        inMethod);
  45.  
  46. static void Sound_ConsumeEvent(
  47.     WindowPtr            inWindow,
  48.     const EventRecord*    inEvent,
  49.     Boolean*            outConsumed);
  50.  
  51. static void Sound_Update(
  52.     WindowPtr            inWindow);
  53.  
  54. static Boolean EventProc(
  55.     EventRecord        *inEvent);
  56.  
  57. static pascal void Sound_BoxUserItem(
  58.     DialogPtr            inDialog,
  59.     short                inItem);
  60.  
  61.  
  62. /*******************************************************************************
  63.  *    CheckVersionNumber
  64.  *
  65.  *    Returns true if the given version number is compatible with (i. e not older
  66.  *    than) version inMajor.inMinor.inBug.
  67.  ******************************************************************************/
  68. Boolean CheckVersionNumber(
  69.     const NumVersion*        inVersion,
  70.     UInt8                    inMajor,
  71.     UInt8                    inMinor,
  72.     UInt8                    inBug)
  73. {
  74.     if (inVersion->majorRev != inMajor)
  75.     {
  76.         return inVersion->majorRev > inMajor;
  77.     }
  78.     else
  79.     {
  80.         return inVersion->minorAndBugRev >= inMinor << 4 | inBug;
  81.     }
  82. }
  83.  
  84.  
  85. /* =============================================================================
  86.  *        Sound_Init (external)
  87.  *
  88.  *    Initializes the sound stuff.
  89.  * ========================================================================== */
  90. void Sound_Init(
  91.     void)
  92. {
  93.     OSStatus                    err;
  94.     SoundComponentLink            link;
  95.     NumVersion                    version;
  96.     SSpFilterVersionData        filterVersion;
  97.     
  98.     assert(kFeedbackItem_COUNT == kFeedbackItem_ExpectedCount);
  99.     
  100.     // Check the sound manager version
  101.     version = SndSoundManagerVersion();
  102.     //• IF YOU CAN'T COMPILE THE PREVIOUS LINE, YOU MUST EDIT YOUR Sound.h TO
  103.     //• MAKE SndSoundManagerVersion RETURN THE TYPE NumVersion.
  104.     
  105.     if (!CheckVersionNumber(&version, 3, 2, 1))
  106.     {
  107.         StopAlert(kAlrtID_SoundMgrVersion, NULL);
  108.         // Note: A normal application would bail on 3D sound here
  109.     }
  110.     
  111.     // Allocate the sound channel
  112.     err = SndNewChannel(&gSoundChannel, sampledSynth, initMono, NULL);
  113.     Message_CheckError(err, "Sound_Init", "SndNewChannel");
  114.     
  115.     assert(gSoundChannel != NULL);
  116.     
  117.     // Install the 3D sound filters
  118.     link.description.componentType            = kSoundEffectsType;
  119.     link.description.componentSubType        = kSSpLocalizationSubType;
  120.     link.description.componentManufacturer    = 0;
  121.     link.description.componentFlags            = 0;        
  122.     link.description.componentFlagsMask        = 0;    
  123.     link.mixerID                            = nil;
  124.     link.linkID                                = nil;
  125.     
  126.     SndSetInfo(gSoundChannel, siPreMixerSoundComponent, &link);
  127.     Message_CheckError(err, "Sound_Init", "SndNewChannel");
  128.     
  129.     // Verify that the right version filter was installed
  130.     filterVersion.manufacturer = 0;
  131.     SndGetInfo(gSoundChannel, siSSpFilterVersion, &filterVersion);
  132.     Message_CheckError(err, "Sound_Init", "SndNewChannel");
  133.     
  134.     switch (filterVersion.manufacturer)
  135.     {
  136.         case 0:
  137.             StopAlert(kAlrtID_FilterNotInstalled, NULL);
  138.             // Note: A normal application would bail on 3D sound here
  139.         break;
  140.         
  141.         case kAppleManufacturer:
  142.             if (!CheckVersionNumber(&filterVersion.version, 1, 0, 0))
  143.             {
  144.                 StopAlert(kAlrtID_FilterVersion, NULL);
  145.                 // Note: A normal application would bail on 3D sound here
  146.             }
  147.         break;
  148.     }
  149.  
  150.     // Grab the dialog
  151.     gSoundDialog = GetNewDialog(kDlogID_Feedback, NULL, (WindowPtr) -1);
  152.     assert(gSoundDialog != NULL);
  153.     
  154.     // Set up our method table
  155.     Window_New(gSoundDialog, Sound_MetaHandler);
  156.     
  157.     // Show the dialog
  158.     ShowWindow(gSoundDialog);
  159.     
  160.     // Initialize the SSpLocalizationData state to garbage
  161.     memset(&gSoundPrev3DInfo, 0x55, sizeof(SSpLocalizationData));
  162. }
  163.  
  164.  
  165. /* =============================================================================
  166.  *        Sound_Exit (external)
  167.  *
  168.  *    Prepares for exit.
  169.  * ========================================================================== */
  170. void Sound_Exit(
  171.     void)
  172. {
  173.     Sound_PlaySilence();
  174.     assert(gSoundResource == NULL);
  175.     
  176.     if (gSoundChannel != NULL)
  177.     {
  178.         SndDisposeChannel(gSoundChannel, true);
  179.         gSoundChannel = NULL;
  180.     }
  181.     
  182.     if (gSoundDialog != NULL)
  183.     {
  184.         DisposeDialog(gSoundDialog);
  185.         gSoundDialog = NULL;
  186.     }
  187. }
  188.  
  189.  
  190. /* =============================================================================
  191.  *        Sound_MetaHandler (internal)
  192.  *
  193.  *    Returns the method function pointer that corresponds to the given ID.
  194.  * ========================================================================== */
  195. WindowMethodPtr Sound_MetaHandler(
  196.     WindowMethod        inMethod)
  197. {
  198.     WindowMethodPtr        result;
  199.     
  200.     result = NULL;
  201.     
  202.     switch (inMethod)
  203.     {
  204.         case kWindowMethod_ConsumeEvent:
  205.             result = (WindowMethodPtr) Sound_ConsumeEvent;
  206.         break;
  207.         
  208.         case kWindowMethod_Update:
  209.             result = (WindowMethodPtr) Sound_Update;
  210.         break;
  211.     }
  212.     
  213.     return result;
  214. }
  215.  
  216.  
  217. /* =============================================================================
  218.  *        Sound_ConsumeEvent (internal)
  219.  *
  220.  *    Called for each event when this is the front window.
  221.  * ========================================================================== */
  222. void Sound_ConsumeEvent(
  223.     WindowPtr            inWindow,
  224.     const EventRecord*    inEvent,
  225.     Boolean*            outConsumed)
  226. {
  227.     Boolean                consumed;
  228.     WindowPtr            window;
  229.     short                item;
  230.     
  231.     assert(inEvent != NULL);
  232.     assert(outConsumed != NULL);
  233.     
  234.     consumed = false;
  235.     
  236.     if (inEvent->what == activateEvt)
  237.     {
  238.         // We need to look at the activate event here because it is
  239.         // consumed by IsDialogEvent/DialogSelect below and so never
  240.         // gets to the window stuff
  241.         window = (WindowPtr) inEvent->message;
  242.         
  243.         if (inEvent->modifiers & activeFlag)
  244.         {
  245.             Window_Activate(window);
  246.         }
  247.         else
  248.         {
  249.             Window_Deactivate(window);
  250.         }
  251.     }
  252.         
  253.     // Do dialog stuff
  254.     if (inEvent->what != keyDown || (inEvent->modifiers & cmdKey) == 0)
  255.     {
  256.         consumed = IsDialogEvent(inEvent);
  257.         if (consumed)
  258.         {
  259.             DialogSelect(inEvent, &window, &item);
  260.         }
  261.     }
  262.     
  263.     // Return the result
  264.     *outConsumed = consumed;
  265. }
  266.  
  267.  
  268. /* =============================================================================
  269.  *        Sound_Update (internal)
  270.  *
  271.  *    Updates the contents of the window.
  272.  * ========================================================================== */
  273. void Sound_Update(
  274.     WindowPtr            inWindow)
  275. {
  276.     DrawDialog(inWindow);
  277. }
  278.  
  279.  
  280. /* =============================================================================
  281.  *        Sound_Configure (external)
  282.  *
  283.  *    Stops the current sound, puts up the Configure dialog box, and resumes the
  284.  *    stopped sound.
  285.  * ========================================================================== */
  286. void Sound_Configure(
  287.     void)
  288. {
  289.     OSStatus            err;
  290.     Boolean                playing;
  291.     short                resID;
  292.     ResType                resType;
  293.     Str255                resName;
  294.     
  295.     // Find out which sound to restore
  296.     playing = gSoundResource != NULL;
  297.     
  298.     if (playing)
  299.     {
  300.         GetResInfo((Handle) gSoundResource, &resID, &resType, resName);
  301.     }
  302.     
  303.     // Quiet
  304.     Sound_PlaySilence();
  305.     
  306.     // Configure
  307.     err = SSpConfigureSetup(EventProc);
  308.     Message_CheckError(err, "Sound_Configure", "SSpConfigureSetup");
  309.     
  310.     // Play it again, Sam
  311.     if (playing)
  312.     {
  313.         Sound_PlayResource(resName);
  314.     }
  315. }
  316.  
  317.  
  318. /* =============================================================================
  319.  *        EventProc (internal)
  320.  *
  321.  *    Called to process events during the 3D sound Configure dialog.  Returns
  322.  *    true if the event was handled (except for update events).
  323.  * ========================================================================== */
  324. Boolean EventProc(
  325.     EventRecord        *inEvent)
  326. {
  327.     WindowPtr                wind;
  328.     
  329.     assert(inEvent != NULL);
  330.     
  331.     if (inEvent->what == updateEvt)
  332.     {
  333.         wind = (WindowPtr) inEvent->message;
  334.         
  335.         if (Window_IsMine(wind))
  336.         {
  337.             SetPort(wind);
  338.             BeginUpdate(wind);
  339.             Window_Update(wind);
  340.             EndUpdate(wind);
  341.         }
  342.     }
  343.     
  344.     return false;
  345. }
  346.  
  347.  
  348. /* =============================================================================
  349.  *        Sound_PlaySilence (external)
  350.  *
  351.  *    Stops any sound that is playing.
  352.  * ========================================================================== */
  353. void Sound_PlaySilence(
  354.     void)
  355. {
  356.     OSStatus            err;
  357.     SndCommand            sndCommand;
  358.     
  359.     sndCommand.cmd = quietCmd;
  360.     sndCommand.param1 = 0;
  361.     sndCommand.param2 = 0;
  362.     err = SndDoImmediate(gSoundChannel, &sndCommand);
  363.     Message_CheckError(err, "Sound_PlaySilence", "SndDoImmediate");
  364.     
  365.     if (gSoundResource != NULL)
  366.     {
  367.         ReleaseResource((Handle) gSoundResource);
  368.         gSoundResource = NULL;
  369.     }
  370. }
  371.  
  372.  
  373. /* =============================================================================
  374.  *        Sound_PlayResource (external)
  375.  *
  376.  *    Plays the 'snd ' resource that has the given name.  Returns true if
  377.  *    successful; returns false if unsuccessful and therefore silence is happening.
  378.  * ========================================================================== */
  379. Boolean Sound_PlayResource(
  380.     Str255                inSndName)
  381. {
  382.     OSStatus            err;
  383.     SndCommand            sndCommand;
  384.     long                offset;
  385.     
  386.     // Silence the sound channel and get rid of the old resource
  387.     Sound_PlaySilence();
  388.     
  389.     // Grab the resource
  390.     gSoundResource = (SndListHandle) GetNamedResource('snd ', inSndName);
  391.     if (gSoundResource == NULL || ResError() != noErr)
  392.     {
  393.         StopAlert(kAlrtID_BadSndLoad, NULL);
  394.         goto bail;
  395.     }
  396.     
  397.     // Lock it down
  398.     HLockHi((Handle) gSoundResource);
  399.     
  400.     // Play it indefinitely
  401.     GetSoundHeaderOffset(gSoundResource, &offset);
  402.     
  403.     sndCommand.cmd = soundCmd;
  404.     sndCommand.param1 = 0;
  405.     sndCommand.param2 = (long) *gSoundResource + offset;
  406.     err = SndDoImmediate(gSoundChannel, &sndCommand);
  407.     Message_CheckError(err, "Sound_PlayResource", "SndDoImmediate");
  408.  
  409.     sndCommand.cmd = freqCmd;
  410.     sndCommand.param1 = 0;
  411.     sndCommand.param2 = 60;
  412.     err = SndDoImmediate(gSoundChannel, &sndCommand);
  413.     Message_CheckError(err, "Sound_PlayResource", "SndDoImmediate");
  414.     
  415.     return true;
  416.  
  417.     // Error exit
  418. bail:
  419.     if (gSoundResource != NULL)
  420.     {
  421.         ReleaseResource((Handle) gSoundResource);
  422.         gSoundResource = NULL;
  423.     }
  424.     
  425.     return false;
  426. }
  427.  
  428.  
  429. /* =============================================================================
  430.  *        Sound_Set3DInfo (external)
  431.  *
  432.  *    Sends the given 3D info to the sound channel.
  433.  * ========================================================================== */
  434. void Sound_Set3DInfo(
  435.     const SSpLocalizationData*    in3DInfo)
  436. {
  437.     OSStatus            err;
  438.     Str255                str;
  439.     UnsignedWide        time;
  440.     
  441.     static UnsignedWide    prevTime = {0, 0};
  442.     
  443.     assert(in3DInfo != NULL);
  444.     
  445.     // Change the filter
  446.     err = SndSetInfo(gSoundChannel, siSSpLocalization, (SSpLocalizationData*) in3DInfo);
  447.     Message_CheckError(err, "Sound_Set3DInfo", "SndSetInfo");
  448.     
  449.     // Update the dialog
  450.     Microseconds(&time);
  451.     
  452.     Utils_SetUInt32Field(
  453.         gSoundDialog,
  454.         kFeedbackItem_Updates,
  455.         1000000.0 / (time.lo-prevTime.lo),
  456.         true);
  457.     
  458.     prevTime = time;
  459.     
  460.     if (gSoundPrev3DInfo.cpuLoad != in3DInfo->cpuLoad)
  461.     {
  462.         Utils_SetUInt32Field(
  463.             gSoundDialog,
  464.             kFeedbackItem_CPULoad,
  465.             in3DInfo->cpuLoad,
  466.             true);
  467.         
  468.         gSoundPrev3DInfo.cpuLoad = in3DInfo->cpuLoad;
  469.     }
  470.     
  471.     if (gSoundPrev3DInfo.medium != in3DInfo->medium)
  472.     {
  473.         switch (in3DInfo->medium)
  474.         {
  475.             case kSSpMedium_Air:
  476.                 strcpy((char*) str, (char*) "\pkSSp…Air");
  477.             break;
  478.             
  479.             case kSSpMedium_Water:
  480.                 strcpy((char*) str, (char*) "\pkSSp…Water");
  481.             break;
  482.             
  483.             default:
  484.                 sprintf((char*) str, "x<<%lu>>", (unsigned long) in3DInfo->medium);
  485.                 str[0] = strlen((char*) str) - 1;
  486.         }
  487.         
  488.         Utils_SetStr255Field(
  489.             gSoundDialog,
  490.             kFeedbackItem_Medium,
  491.             str,
  492.             true);
  493.         
  494.         gSoundPrev3DInfo.medium = in3DInfo->medium;
  495.     }
  496.     
  497.     if (gSoundPrev3DInfo.humidity != in3DInfo->humidity)
  498.     {
  499.         Utils_SetFloatField(
  500.             gSoundDialog,
  501.             kFeedbackItem_Humidity,
  502.             in3DInfo->humidity,
  503.             true);
  504.         
  505.         gSoundPrev3DInfo.humidity = in3DInfo->humidity;
  506.     }
  507.     
  508.     if (gSoundPrev3DInfo.roomSize != in3DInfo->roomSize)
  509.     {
  510.         Utils_SetFloatField(
  511.             gSoundDialog,
  512.             kFeedbackItem_RoomSize,
  513.             in3DInfo->roomSize,
  514.             true);
  515.         
  516.         gSoundPrev3DInfo.roomSize = in3DInfo->roomSize;
  517.     }
  518.     
  519.     if (gSoundPrev3DInfo.roomReflectivity != in3DInfo->roomReflectivity)
  520.     {
  521.         Utils_SetFloatField(
  522.             gSoundDialog,
  523.             kFeedbackItem_RoomReflectivity,
  524.             in3DInfo->roomReflectivity,
  525.             true);
  526.         
  527.         gSoundPrev3DInfo.roomReflectivity = in3DInfo->roomReflectivity;
  528.     }
  529.     
  530.     if (gSoundPrev3DInfo.reverbAttenuation != in3DInfo->reverbAttenuation)
  531.     {
  532.         Utils_SetFloatField(
  533.             gSoundDialog,
  534.             kFeedbackItem_ReverbAttenuation,
  535.             in3DInfo->reverbAttenuation,
  536.             true);
  537.         
  538.         gSoundPrev3DInfo.reverbAttenuation = in3DInfo->reverbAttenuation;
  539.     }
  540.     
  541.     if (gSoundPrev3DInfo.sourceMode != in3DInfo->sourceMode)
  542.     {
  543.         switch (in3DInfo->sourceMode)
  544.         {
  545.             case kSSpSourceMode_Unfiltered:
  546.                 strcpy((char*) str, (char*) "\pkSSp…Unfiltered");
  547.             break;
  548.             
  549.             case kSSpSourceMode_Localized:
  550.                 strcpy((char*) str, (char*) "\pkSSp…Localized");
  551.             break;
  552.             
  553.             case kSSpSourceMode_Ambient:
  554.                 strcpy((char*) str, (char*) "\pkSSp…Ambient");
  555.             break;
  556.             
  557.             case kSSpSourceMode_Binaural:
  558.                 strcpy((char*) str, (char*) "\pkSSp…Binaural");
  559.             break;
  560.             
  561.             default:
  562.                 sprintf((char*) str, "x<<%lu>>", (unsigned long) in3DInfo->sourceMode);
  563.                 str[0] = strlen((char*) str) - 1;
  564.         }
  565.         
  566.         Utils_SetStr255Field(
  567.             gSoundDialog,
  568.             kFeedbackItem_SourceMode,
  569.             str,
  570.             true);
  571.         
  572.         gSoundPrev3DInfo.sourceMode = in3DInfo->sourceMode;
  573.     }
  574.     
  575.     if (gSoundPrev3DInfo.referenceDistance != in3DInfo->referenceDistance)
  576.     {
  577.         Utils_SetFloatField(
  578.             gSoundDialog,
  579.             kFeedbackItem_ReferenceDistance,
  580.             in3DInfo->referenceDistance,
  581.             true);
  582.         
  583.         gSoundPrev3DInfo.referenceDistance = in3DInfo->referenceDistance;
  584.     }
  585.     
  586.     if (gSoundPrev3DInfo.coneAngleCos != in3DInfo->coneAngleCos)
  587.     {
  588.         Utils_SetFloatField(
  589.             gSoundDialog,
  590.             kFeedbackItem_ConeAngleCos,
  591.             in3DInfo->coneAngleCos,
  592.             true);
  593.         
  594.         gSoundPrev3DInfo.coneAngleCos = in3DInfo->coneAngleCos;
  595.     }
  596.     
  597.     if (gSoundPrev3DInfo.coneAttenuation != in3DInfo->coneAttenuation)
  598.     {
  599.         Utils_SetFloatField(
  600.             gSoundDialog,
  601.             kFeedbackItem_ConeAttenuation,
  602.             in3DInfo->coneAttenuation,
  603.             true);
  604.         
  605.         gSoundPrev3DInfo.coneAttenuation = in3DInfo->coneAttenuation;
  606.     }
  607.     
  608.     if (gSoundPrev3DInfo.currentLocation.elevation != in3DInfo->currentLocation.elevation)
  609.     {
  610.         Utils_SetFloatField(
  611.             gSoundDialog,
  612.             kFeedbackItem_Elevation,
  613.             in3DInfo->currentLocation.elevation,
  614.             true);
  615.         
  616.         gSoundPrev3DInfo.currentLocation.elevation = in3DInfo->currentLocation.elevation;
  617.     }
  618.     
  619.     if (gSoundPrev3DInfo.currentLocation.azimuth != in3DInfo->currentLocation.azimuth)
  620.     {
  621.         Utils_SetFloatField(
  622.             gSoundDialog,
  623.             kFeedbackItem_Azimuth,
  624.             in3DInfo->currentLocation.azimuth,
  625.             true);
  626.         
  627.         gSoundPrev3DInfo.currentLocation.azimuth = in3DInfo->currentLocation.azimuth;
  628.     }
  629.     
  630.     if (gSoundPrev3DInfo.currentLocation.distance != in3DInfo->currentLocation.distance)
  631.     {
  632.         Utils_SetFloatField(
  633.             gSoundDialog,
  634.             kFeedbackItem_Distance,
  635.             in3DInfo->currentLocation.distance,
  636.             true);
  637.         
  638.         gSoundPrev3DInfo.currentLocation.distance = in3DInfo->currentLocation.distance;
  639.     }
  640.     
  641.     if (gSoundPrev3DInfo.currentLocation.projectionAngle != in3DInfo->currentLocation.projectionAngle)
  642.     {
  643.         Utils_SetFloatField(
  644.             gSoundDialog,
  645.             kFeedbackItem_ProjectionAngle,
  646.             in3DInfo->currentLocation.projectionAngle,
  647.             true);
  648.         
  649.         gSoundPrev3DInfo.currentLocation.projectionAngle = in3DInfo->currentLocation.projectionAngle;
  650.     }
  651.     
  652.     if (gSoundPrev3DInfo.currentLocation.sourceVelocity != in3DInfo->currentLocation.sourceVelocity)
  653.     {
  654.         Utils_SetFloatField(
  655.             gSoundDialog,
  656.             kFeedbackItem_SourceVelocity,
  657.             in3DInfo->currentLocation.sourceVelocity,
  658.             true);
  659.         
  660.         gSoundPrev3DInfo.currentLocation.sourceVelocity = in3DInfo->currentLocation.sourceVelocity;
  661.     }
  662.     
  663.     if (gSoundPrev3DInfo.currentLocation.listenerVelocity != in3DInfo->currentLocation.listenerVelocity)
  664.     {
  665.         Utils_SetFloatField(
  666.             gSoundDialog,
  667.             kFeedbackItem_ListenerVelocity,
  668.             in3DInfo->currentLocation.listenerVelocity,
  669.             true);
  670.         
  671.         gSoundPrev3DInfo.currentLocation.listenerVelocity = in3DInfo->currentLocation.listenerVelocity;
  672.     }
  673.     
  674.     if (gSoundPrev3DInfo.reserved0 != in3DInfo->reserved0)
  675.     {
  676.         Utils_SetFloatField(
  677.             gSoundDialog,
  678.             kFeedbackItem_Reserved0,
  679.             in3DInfo->reserved0,
  680.             true);
  681.         
  682.         gSoundPrev3DInfo.reserved0 = in3DInfo->reserved0;
  683.     }
  684.     
  685.     if (gSoundPrev3DInfo.reserved1 != in3DInfo->reserved1)
  686.     {
  687.         Utils_SetFloatField(
  688.             gSoundDialog,
  689.             kFeedbackItem_Reserved1,
  690.             in3DInfo->reserved1,
  691.             true);
  692.         
  693.         gSoundPrev3DInfo.reserved1 = in3DInfo->reserved1;
  694.     }
  695.     
  696.     if (gSoundPrev3DInfo.reserved2 != in3DInfo->reserved2)
  697.     {
  698.         Utils_SetFloatField(
  699.             gSoundDialog,
  700.             kFeedbackItem_Reserved2,
  701.             in3DInfo->reserved2,
  702.             true);
  703.         
  704.         gSoundPrev3DInfo.reserved2 = in3DInfo->reserved2;
  705.     }
  706.     
  707.     if (gSoundPrev3DInfo.reserved3 != in3DInfo->reserved3)
  708.     {
  709.         Utils_SetFloatField(
  710.             gSoundDialog,
  711.             kFeedbackItem_Reserved3,
  712.             in3DInfo->reserved3,
  713.             true);
  714.         
  715.         gSoundPrev3DInfo.reserved3 = in3DInfo->reserved3;
  716.     }
  717.     
  718.     if (gSoundPrev3DInfo.virtualSourceCount != in3DInfo->virtualSourceCount)
  719.     {
  720.         Utils_SetFloatField(
  721.             gSoundDialog,
  722.             kFeedbackItem_VirtualSourceCount,
  723.             in3DInfo->virtualSourceCount,
  724.             true);
  725.         
  726.         gSoundPrev3DInfo.virtualSourceCount = in3DInfo->virtualSourceCount;
  727.     }
  728. }
  729.  
  730.  
  731.